package exchange

import (
	"github.com/garyburd/redigo/redis"
	"global/libs/structs"
	"sync"
	"sort"
	"github.com/shopspring/decimal"
	"global/core"
	"global/constants"
	"global/model"
	"os"
	"github.com/ngaut/log"
)

type PairSort struct {
	pool 		*redis.Pool
	slug 		string
	tickers 	[]*structs.Ticker

	pairs 		map[string]interface{}

	mux 		sync.Mutex
	rmux 		sync.RWMutex
}

// redis 连接池和交易所名称
func NewPairSort(pool *redis.Pool, slug string) *PairSort {
	s := &PairSort{
		pool: 	pool,
		slug: 	slug,
		pairs: 	make(map[string]interface{}),
	}
	s.pairs = s.getEnabledSymbols()
	return s
}

func (s *PairSort) getEnabledSymbols() map[string]interface{} {
	pairs, err := model.ExchangePairModel.GetEnableSymbolsBySlug(s.slug)
	if err != nil {
		log.Errorf("Error: get enabled symbols failed, err: %s", err)
		os.Exit(1)
	}
	symbols := make(map[string]interface{})
	for _, v := range pairs {
		symbols[v.Symbol] = true
	}
	return symbols
}

func (s *PairSort) StartSort(tickers []*structs.Ticker)  {
	s.tickers = tickers
	go s.sortByAmount()
	go s.sortByPrice()
	go s.sortByPercent()
}

func (s *PairSort) sortByAmount()  {
	conn := s.pool.Get()
	defer conn.Close()

	tickers := s.copyTickers()
	sort.Slice(tickers, func(i, j int) bool {
		iAmount, _ := decimal.NewFromString(tickers[i].AmountUsd)
		jAmount, _ := decimal.NewFromString(tickers[j].AmountUsd)
		return iAmount.GreaterThan(jAmount)
	})

	// desc
	descData := make([]string, 0)
	s.rmux.RLock()
	for _, v := range tickers {
		if _, ok := s.pairs[v.Symbol]; ok {
			descData = append(descData, v.Symbol)
		}
	}
	s.rmux.RUnlock()

	ascData := make([]string, 0)
	for i:=len(descData)-1; i>=0;i-- {
		ascData = append(ascData, descData[i])
	}

	core.SaveAnalysisPairSorted(conn, s.slug, "amount", constants.SortTypeDesc, descData)
	core.SaveAnalysisPairSorted(conn, s.slug, "amount", constants.SortTypeAsc, ascData)

}

func (s *PairSort) copyTickers() []*structs.Ticker {
	s.mux.Lock()
	src := make([]*structs.Ticker, len(s.tickers))
	copy(src, s.tickers[:])
	s.mux.Unlock()
	return src
}

func (s *PairSort) sortByPrice()  {
	conn := s.pool.Get()
	defer conn.Close()

	tickers := s.copyTickers()
	sort.Slice(tickers, func(i, j int) bool {
		iAmount, _ := decimal.NewFromString(tickers[i].PriceUsd)
		jAmount, _ := decimal.NewFromString(tickers[j].PriceUsd)
		return iAmount.GreaterThan(jAmount)
	})

	// desc
	descData := make([]string, 0)
	s.rmux.RLock()
	for _, v := range tickers {
		if _, ok := s.pairs[v.Symbol]; ok {
			descData = append(descData, v.Symbol)
		}
	}
	s.rmux.RUnlock()

	ascData := make([]string, 0)
	for i:=len(descData)-1; i>=0;i-- {
		ascData = append(ascData, descData[i])
	}

	core.SaveAnalysisPairSorted(conn, s.slug, "price", constants.SortTypeDesc, descData)
	core.SaveAnalysisPairSorted(conn, s.slug, "price", constants.SortTypeAsc, ascData)
}

func (s *PairSort) sortByPercent() {
	conn := s.pool.Get()
	defer conn.Close()

	tickers := s.copyTickers()
	sort.Slice(tickers, func(i, j int) bool {
		iAmount, _ := decimal.NewFromString(tickers[i].Percent)
		jAmount, _ := decimal.NewFromString(tickers[j].Percent)
		return iAmount.GreaterThan(jAmount)
	})

	// desc
	descData := make([]string, 0)
	for _, v := range tickers {
		s.rmux.RLock()
		if _, ok := s.pairs[v.Symbol]; ok {
			descData = append(descData, v.Symbol)
		}
		s.rmux.RUnlock()
	}

	ascData := make([]string, 0)
	for i:=len(descData)-1; i>=0;i-- {
		ascData = append(ascData, descData[i])
	}

	core.SaveAnalysisPairSorted(conn, s.slug, "percent", constants.SortTypeDesc, descData)
	core.SaveAnalysisPairSorted(conn, s.slug, "percent", constants.SortTypeAsc, ascData)
}

